package com.gabry.goodkill.actor

import akka.actor.{Actor, ActorLogging, ActorPath, Props}
import akka.util.Timeout
import com.gabry.goodkill.protocol._

import scala.concurrent.ExecutionContextExecutor

/**
 * Created by gabry on 2018/9/19 17:11
 */
class GoodActor(goodKillId:GOOD_KILL_ID_TYPE,activityId:ACTIVITY_ID_TYPE) extends Actor with ActorLogging{
  private val cacheActorPath = s"/user/$activityId-cache-*"
  private val stateActorPath = s"/user/$activityId-state"
  private val cacheActorSucNumber = 3
  // 该商品没有被抢到时的行为
  private def unPurchasedReceive:Receive = {
    case purchase: Purchase =>
      val placeOrderActor = context.actorOf(Props(new PlaceOrderActor(goodKillId,cacheActorPath,cacheActorSucNumber)),s"${self.path.name}-placeOrder")
      placeOrderActor ! purchase
      context.become(purchasingReceive)
  }
  // 订单被抢购中
  private def purchasingReceive:Receive = {
    case _: Purchase =>
     // log.info("订单抢购中，不再处理抢购消息")
    case purchased:Purchased =>
      context.become(purchasedReceive)
      self ! purchased
    case PurchaseFailed =>
      log.info(s"用户抢购失败")
      context.become(unPurchasedReceive)
  }
  // 该商品已经被抢购
  private def purchasedReceive:Receive = {
    case purchase: Purchased =>
      context.actorSelection(stateActorPath) ! purchase
      context.stop(self)
    case otherMessage =>
    //  log.warning(s"商品已经被抢购 $otherMessage")
  }

  override def receive: Receive = unPurchasedReceive

}
class PlaceOrderActor(goodKillId:GOOD_KILL_ID_TYPE,cacheActorPath:String,cacheActorSucNumber:Int) extends Actor with ActorLogging {
  import scala.concurrent.duration._
  private implicit val executionContext: ExecutionContextExecutor = context.dispatcher
  context.setReceiveTimeout(3 seconds)
  private def waitPlaceOrderResultReceive(purchasedNumber:Int):Receive = {
    case purchased:Purchased =>
      if( purchasedNumber >= cacheActorSucNumber-1 ){
       // log.info(s"抢购成功，已经超过 $cacheActorSucNumber 个cache actor记录了此次抢购请求")
        context.parent ! purchased
        context.stop(self)
      }else{
        context.become( waitPlaceOrderResultReceive( purchasedNumber + 1 ) )
      }
    case  PurchaseFailed =>
      log.error(s"place order failed")
    case _:Timeout =>
      context.parent ! PurchaseFailed
      context.stop(self)
  }
  override def receive: Receive = {
    case purchase: Purchase =>
      context.actorSelection(cacheActorPath) ! PlaceOrder(purchase.userKillId,purchase.activityId,goodKillId)
      context.become(waitPlaceOrderResultReceive(0))
  }
}